
type point =
  {
    mutable x : float ;
    mutable y : float ;
    mutable z : float ;
  }



(**************************** fonction prerequise *****************************)

(* inverse une liste*)
let inverse_list l =
  let rec inverse la lb = match la with
    |[] -> lb
    |e::l1 -> inverse l1 (e::lb)
  in
  inverse l []

let recup_color_haut path =
  let fic_color = open_in path in
  let nb_color = int_of_string(input_line fic_color) in
    let l = ref [] in
    let th = Array.init nb_color  (fun _ ->  0) in
    for i = 0 to nb_color - 1 do
      ignore(input_line fic_color);
      let r = int_of_string(input_line fic_color) in
      let g = int_of_string(input_line fic_color) in
      let b = int_of_string(input_line fic_color) in
      let h = int_of_string(input_line fic_color) in
	l := (r,g,b)::!l;
	th.(i)<- h;
    done;
      close_in  fic_color;
      (inverse_list(!l),th)
(******************************************************************************)

(* init de SDL *)
let sdl_init () =
    Sdl.init [`EVERYTHING];
    Sdlevent.enable_events Sdlevent.all_events_mask

(* Dimensions d'une image *)
let get_dims img =
  ((Sdlvideo.surface_info img).Sdlvideo.w
, (Sdlvideo.surface_info img).Sdlvideo.h)



(*transforme les faces en couples *)
let string2couple s =
  let i = String.index s ' ' in
  let a = int_of_string(String.sub s  0 ( i ))in
  let str = (String.sub s (i+1) (String.length(s) - i - 1))in
  let i2 =String.index str ' 'in
  let b = int_of_string(String.sub str 0 (i2)) in
  let c = int_of_string(String.sub str (i2+1) ((String.length(str))-i2 -1))in
    (a,b,c)

(*transforme les points en points !!!*)
let convert2point s  =
  let i = String.index s ' ' in
  let a = float_of_string(String.sub s  0 ( i ))in
  let str = (String.sub s (i+1) (String.length(s) - i - 1))in
  let i2 =String.index str ' 'in
  let b = float_of_string(String.sub str 0 (i2)) in
  let c = float_of_string(String.sub str (i2+1) ((String.length(str))-i2 -1))in
    { x = a ; y = b; z = c }

(*Donne la bonne position du point dans tableau *)
let give_pos l  pos  =
  List.nth l (List.length l - pos -1)


(*Lis le fichier obj et le met les points dans des tableaux et les
  faces dans une liste *)
let read path liste_faces tab_point =

  let txt = open_in  path in
  let l1 = ref (input_line txt) in
  let list =ref  [] in

    try

      while (!l1 = "")||(String.sub !l1 0 1 <> "v")  do
	l1 := input_line  txt;
      done;

      while(String.sub !l1 0 1 = "v")do
	list:=convert2point(String.sub !l1 2 (String.length(!l1) - 2))::!list;
	l1 := input_line  txt;
      done;

      let long = List.length(!list) in
	tab_point := Array.init long  (give_pos !list  );

	  while (!l1 = "")||(String.sub !l1 0 1 <> "f")  do
	    l1 := input_line  txt;
	  done;

	  while (String.sub !l1 0 1 = "f") do
            liste_faces :=  string2couple
	      (String.sub !l1 2 (String.length(!l1)-2)) :: !liste_faces;
	    l1 := input_line  txt;
	  done;

    with End_of_file -> close_in txt

let give_color (lc,th) z =
  let i= ref 0 in
    while(!i < (Array.length th) -1)&& (th.(!i)<> z) do
    i := !i + 1;
  done;
  List.nth lc (!i)

let rec draw tp (lc,th) = function
  |  [] -> GlDraw.ends ();
  |(p1,p2,p3)::l->
     let d = tp.(p1-1) in
     let e = tp.(p2-1) in
     let f = tp.(p3-1) in
     let (r,g,b)= give_color (lc,th) (int_of_float(d.z)) in
       GlDraw.color (float_of_int( r*255) ,float_of_int (g*255),float_of_int(b*255)) ;
     GlDraw.vertex3 (d.x,d.y,d.z);
     let (r,g,b)= give_color (lc,th) (int_of_float(e.z)) in
     GlDraw.color (float_of_int( r*255) ,float_of_int (g*255),float_of_int(b*255)) ;
     GlDraw.vertex3 (e.x,e.y,e.z);
     let (r,g,b)=  give_color (lc,th) (int_of_float(f.z)) in
     GlDraw.color (float_of_int( r*255) ,float_of_int (g*255),float_of_int(b*255)) ;
     GlDraw.vertex3 (f.x,f.y,f.z);
     draw tp (lc,th) l

let main () =
  sdl_init ();
  let liste_faces = ref [] in
  let tab_point = ref [||] in
  read "../image/map.obj"   liste_faces tab_point;
  let c = recup_color_haut "../image/color.txt" in
  ignore( Glut.init Sys.argv );
  Glut.initWindowSize ~w:800 ~h:600;
  Glut.initDisplayMode ~double_buffer:true ~depth:true ();
  ignore (Glut.createWindow ~title:"Motor3D");
    (*    let angle t = 10. *. t *. t in*)
  let render () =
      (* on efface le buffer dans lequel on dessine *)
    GlClear.color (0.0, 0.0, 0.0);(* <- couleur de fond = noir *)
    GlClear.clear [ `color; `depth ];
    GlMat.mode `modelview;
    GlMat.load_identity();
    GluMat.perspective ~fovy:70.0 ~aspect:(800. /. 600.) ~z:(1.,2000.0);
    GluMat.look_at ~eye:(256.,256.,512.)
      ~center:(256.,256.,0.) ~up:(0.,1.,0.);
    Gl.enable `depth_test;
    (*GlMat.rotate ~angle: (angle ( 1.00005*.Sys.time() )) ~z:1. ();*)
    GlDraw.begins `(*line_strip*)triangles;
   draw !tab_point c !liste_faces;
    (*GlDraw.color (255.,0.,0.);
      List.iter GlDraw.vertex3 [-0.5, -0.5 ,0.; 0., 0.5 ,0.; 0.5,-0.5,0.];
      GlDraw.color (0.,255.,0.);
      List.iter GlDraw.vertex3 [ 0.5, -0.5,0. ; 0., 0.5 ,0.;-0.5,-0.5,0.5];
      GlDraw.color (0.,0.,255.);
      List.iter GlDraw.vertex3 [-0.5,-0.5,0.5; 0., 0.5 ,0.;-0.5, -0.5 ,0. ];
      GlDraw.ends ();*)
    Glut.swapBuffers () in
    GlMat.mode `modelview;
    Glut.displayFunc ~cb:render;
    Glut.idleFunc ~cb:(Some Glut.postRedisplay);
    Glut.mainLoop ()


let _ = main ()

